#ifndef     __THREAD_H
#define     __THREAD_H

#include "./rtos.h"
#include "../utils/assert.h"
#include "../utils/no_copyable.h"
#include <type_traits>

namespace rtos {

template <typename Task, uint32_t StackSize, osPriority_t Priority, uint32_t Attr = osThreadDetached>
class Thread : private utils::no_copyable_t {
public:
    using ThisType = Thread<Task, StackSize, Priority, Attr>;

    void start(const char *name = "unknown") {
        osThreadAttr_t attr;
        attr.name = name;
        attr.attr_bits = Attr; 
        attr.cb_mem = m_cb_mem;
        attr.cb_size = osRtxThreadCbSize;
        attr.stack_mem = m_stack_mem;
        attr.stack_size = StackSize;
        attr.priority = Priority;
        attr.tz_module = 0;
        attr.reserved = 0;
        m_id = osThreadNew(&ThisType::task_main, this, &attr);
        utils::assert(m_id != NULL);
    }

    template <uint32_t Mode = Attr>
    inline std::enable_if_t<Mode == osThreadJoinable, osStatus_t> 
    join() {
        return osThreadJoin(m_id);
    }

private:
    static void task_main(void *arg) {
        static_cast<Task *>(arg)->run();
    }

private:
    osThreadId_t m_id;
    uint64_t m_cb_mem[(osRtxThreadCbSize + 7) / 8];
    uint64_t m_stack_mem[ (StackSize + 7) / 8 ];
};



}


#endif
